#!/usr/bin/env ruby
# This class is used to render logger notification elements.
class RedBook::Renderer
		
		
	attr_accessor :output
	
	# Initialize the renderer.
	def initialize
		reset
	end
	
	# Reset the output buffer.
	def reset
		@output = []
	end
	
	# Render any logger notification element.
	def render(element, options={})
		raise RendererError, "Invalid Element" unless element.xhash?
		options[:level] ||= 0
		case element.name
		when :activity then
			@output << activity(element, options)
		when :tag,:tags,:tagset then;
		when :command then
			unless self.class == RedBook::Renderer then
				@output << command(element)
				render_children(element, options)
				options[:level]-=1
			end
		when :separator then
			@output << separator(element)
		else
			if element.name && respond_to?(element.name) then
				text = send(element.name, element)
				@output << '  '*options[:level]+text unless text.blank?
			else
				text = send(:unknown, element)
				@output << '  '*options[:level]+text unless text.blank?
			end
			unless element.children.blank?
				render_children(element, options)
				options[:level]-=1
			end
		end
	end
	
	protected
	
	# Render a command element.
	def command(element)
		nil
	end
	
	# Render an unknown element.
	def unknown(element)
		label =  make_label(element)
		"#{alt_prompt} #{label}: #{element.value}"
	end
	
	# Render a generic element.
	def generic(element)
		" #{element.value}"
	end
	
	# Render an info element.	
	def info(element)
		"#{prompt.cyan} #{element.value.dark_cyan}"
	end
	
	# Render a warning element.
	def warning(element)
		"#{prompt.yellow} #{element.value.dark_yellow}"
	end
	
	# Render an error element.
	def error(element)
		"#{prompt.red} #{element.value.dark_red}"
	end

	# Render a success element.		
	def success(element)
		"#{prompt.green} #{element.value.dark_green}"
	end
	
	# Render a debug element.
	def debug(element)
		"#{prompt.magenta} #{element.value.dark_magenta}"
	end
	
	# Render a separator element.
	def separator(element)
		element[:separator] ||= '='
		(' '+element[:separator]*57).dark_red
	end
	
	# Render an activity element.
	def activity(a, options={})
		options[:level] ||= 0
		message = ''
		if options[:index] then
			index = (options[:index].to_i > 0) ? options[:index].to_i : 1
			pad = ' '*((Math.log10(options[:total]).floor - Math.log10(index).floor)+1)
			message = pad+options[:index].to_s.cyan
		end
		message += ' '+(a/:start_time).first.value.strftime(RedBook::Config.instance.data[:time_format]).dark_cyan+" "+a.attributes[:message].cyan.encode_in
		message += " "+render_tags(a/:tag).encode_in if !(a/:tag).blank? && (RedBook::Config.instance.data[:show_tags] == true)
		message += "\n#{'  '*options[:level]}#{pad}#{duration({:duration => (a/:duration).first.value})}" unless (a/:duration).blank?
		message
	end
	
	def duration(element)
		"#{alt_prompt.yellow} #{"Duration:".dark_yellow} #{RedBook::TimeCalc.new(element.value).to_s}"
	end

	private
	
	def prompt
		"   >>"
	end
	
	def alt_prompt
		"     -"
	end
	
	def render_children(element, options)
		options[:index]= (options[:index]) ? options[:index]-1 : 0
		options[:level]+=1 unless options[:level].blank?
		options[:total] = (element/:activity).length unless (element/:activity).blank?
		element.children.each do |c|
			options[:index]+=1 if c.name == :activity
			render(c, options)
		end
	end
	
	def render_tags(tags=[])
		colored_tags = []
		tags.each { |t| colored_tags << "[".dark_yellow+t.value.yellow+"]".dark_yellow }
		colored_tags.join.encode_in
	end
	
	def make_label(element)
		(element[:_attributes] && element[:_attributes][:raw]) ? element.name : element.name.to_s.humanize.titleize
	end
	
end
